package com.weilele.mvvm.base.livedata

import android.app.Activity
import android.content.ContextWrapper
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import com.weilele.mvvm.base.helper.observeForeverLiveData
import com.weilele.mvvm.base.helper.observerForeverLiveDataSuccess
import com.weilele.mvvm.base.helper.observerLiveData
import com.weilele.mvvm.base.helper.observerLiveDataSuccess
import com.weilele.mvvm.utils.*
import com.weilele.mvvm.view.SimpleSwitchView

val AppCompatActivity.appCompatActivity
    get() = this

val Fragment.appCompatActivity: AppCompatActivity?
    get() = activity.safeGet()
        ?: if (context is ContextWrapper && context !is Activity)
            (context as? ContextWrapper)?.baseContext?.safeGet()
        else
            context.safeGet()

/**
 * 将LiveBean包装，使注册更简单
 */
sealed class LiveDataWrap {

    abstract fun observer(lifecycle: LifecycleOwner)
    abstract fun observeForever()
    abstract fun removeObserve()

    data class WrapLiveData<T>(
        val liveData: LiveData<T>,
        inline val observer: Observer<T?>,
        val observers: MutableList<Observer<T?>> = mutableListOf()
    ) : LiveDataWrap() {
        override fun observer(lifecycle: LifecycleOwner) {
            observers.add(lifecycle.observerLiveData(liveData, observer))
        }

        override fun observeForever() {
            observers.add(liveData.observeForeverLiveData(observer))
        }

        override fun removeObserve() {
            observers.forEach {
                liveData.removeObserver(it)
            }
            observers.clear()
        }
    }

    data class WrapOnlySuccessLiveData<T>(
        val liveData: LiveData<StatusData<T>>,
        inline val observer: Function1<T, Unit>,
        val observers: MutableList<Observer<StatusData<T>?>> = mutableListOf()
    ) : LiveDataWrap() {
        override fun observer(lifecycle: LifecycleOwner) {
            observers.add(lifecycle.observerLiveDataSuccess(liveData, observer))
        }

        override fun observeForever() {
            observers.add(liveData.observerForeverLiveDataSuccess(observer))
        }

        override fun removeObserve() {
            observers.forEach {
                liveData.removeObserver(it)
            }
            observers.clear()
        }
    }
}

/**
 * 创建一个对象
 */
fun <T> createStatusLiveData() = MutableLiveData<StatusData<T>>()

/**
 * 创建一个对象
 */
fun <T> createStatusListLiveData() = MutableLiveData<StatusData<MutableList<T>>>()

/**
 * 创建一个中介者对象
 */
fun <T> createStatusMediatorLiveData() = MediatorLiveData<StatusData<T>>()

/**
 * 创建一个中介者对象
 */
fun <T> createStatusListMediatorLiveData() = MediatorLiveData<StatusData<MutableList<T>>>()

/**
 * 注册
 */
fun List<LiveDataWrap>?.observer(lifecycle: LifecycleOwner) {
    this?.forEach {
        it.observer(lifecycle)
    }
}

/**
 * 永久注册
 */
fun List<LiveDataWrap>?.observeForever() {
    this?.forEach {
        it.observeForever()
    }
}

/**
 * 移除注册
 */
fun MutableList<LiveDataWrap>?.removeObserver() {
    this?.forEach {
        it.removeObserve()
    }
    this?.clear()
}


/**
 * 提供方法去创建
 */
infix fun <T> LiveData<T>.wrapObserver(observer: Observer<T?>): LiveDataWrap {
    return LiveDataWrap.WrapLiveData(this, observer)
}

/**
 * 提供方法去创建
 */
infix fun <T> LiveData<StatusData<T>>.wrapSuccessObserver(observer: Function1<T, Unit>): LiveDataWrap {
    return LiveDataWrap.WrapOnlySuccessLiveData(this, observer)
}

/**
 * 提供方法去创建
 */
fun <T> LiveData<StatusData<T>>.wrapWithSwitchViewObserver(
    onGetSwitchView: Function0<SimpleSwitchView?>? = null,
    onGetOtherInfo: Function1<StatusData<T>, SimpleSwitchView.OtherInfo?>? = null/*获取额外的显示信息*/,
    onGetLoadingInfo: Function1<StatusData<T>, SimpleSwitchView.LoadingInfo?>? = null/*获取额外的显示信息*/,
    onNullCall: Function1<StatusData<T>?, Unit>? = null/*当值为其他的时候回调*/,
    interceptSuccess: Function1<@ParameterName("success") StatusData<T>, Unit>
): LiveDataWrap {
    return LiveDataWrap.WrapLiveData(this, observer = {
        when (it?.status) {
            StatusData.Error -> {
                val otherInfo = onGetOtherInfo?.invoke(it)
                if (otherInfo == null) {
                    onGetSwitchView?.invoke()?.showOtherView(null)
                } else {
                    onGetSwitchView?.invoke()?.showOtherView(otherInfo)
                }
            }
            StatusData.Running -> {
                val loadingInfo = onGetLoadingInfo?.invoke(it)
                if (loadingInfo == null) {
                    onGetSwitchView?.invoke()?.showLoadingView(null)
                } else {
                    onGetSwitchView?.invoke()?.showLoadingView(loadingInfo)
                }
            }
            StatusData.Success -> {
                onGetSwitchView?.invoke()?.showContentView(null)
                interceptSuccess.invoke(it)
            }
            else -> {
                onNullCall?.invoke(it)
            }
        }
    })
}